/**
 *	\file AKDSQGeometryProvider.m
 *  
 *  \section desc_sec Description
 *  Description
 *  
 *  \if copyright
 *  	Copyright 2008 Ben Chen. All rights reserved.
 *  \endif
 *  
 *  \section hist_sec Change History:
 *  	-	2/21/08		BC		Created this file
 *  
 *  <hr>
 *  \addtogroup AnimalKingdom
 *  @{
 */

#import "AKDSQ.h"
#import "AKDSQGeometryProvider.h"

@implementation AKDSQGeometryProvider

- (id) init {
	self = [super init];
	if (self != nil) {
		chessboardSize = NSMakeSize(571, 512); //NSMakeSize(1024, 670.0);
		
		[self getCellPositions:(NSRect **)cellRects
					   forRect:NSMakeRect(15, 17, 550, 480)//NSMakeRect(237, 80, 565, 475)
				  topRowLength:485
					 numOfRows:7 
				  numOfColumns:9];
	}
	return self;
}

- (NSSize)chessboardSize {
	return chessboardSize;
}

- (BOOL)getCellPositions:(NSRect **)newCellRects
				 forRect:(NSRect)chessboardRect 
			topRowLength:(float)topWidth
			   numOfRows:(unsigned)numOfRows 
			numOfColumns:(unsigned)numOfCols {
	/*
	 |------------------------------------|
	 |                                    |
	 |         /<-  topWidth  ->\         |------
	 |        /                  \        |  /\
	 |       /                    \       |  ||
	 |      /                      \      | height
	 |     /                        \     |  ||
	 |    /                          \    |  \/
	 |   /<-       bottomWidth      ->\   |------
	 |                                    | bottomMargin
	 |------------------------------------|------	 
	 ->|  |<-
	 leftMargin
	 */
	
	BOOL retVal;
	
	if (numOfRows > 0 && numOfCols > 0)
	{
		float bottomWidth = NSWidth(chessboardRect); 
		float height      = NSHeight(chessboardRect);
		
		float bottomMargin	= chessboardRect.origin.y;
		float leftMargin	= chessboardRect.origin.x;
		
		// Calculate the ratio between lengths of two adjacent horizontal lines
		float rowRatio = pow(topWidth/bottomWidth, 1.0/numOfRows);
		
		// Use this value to calculate height later
		float rateOfSlope = (bottomWidth - topWidth) / height;
		
		float marginTopLeft = (bottomWidth - topWidth) / 2;
		int i, j;
		float marginRowLeft, cellWidth;
		
		float floorWidth = bottomWidth;
		float ceilingWidth = floorWidth * rowRatio;
		
		float floorHeight = heightForWidth(floorWidth, bottomWidth, rateOfSlope);
		float ceilingHeight = heightForWidth(ceilingWidth, bottomWidth, rateOfSlope);
		// Calculate from bottom to top
		for (i = 0; i < numOfRows; ++i) {
			marginRowLeft	= (floorHeight + ceilingHeight) / 2 * marginTopLeft / height; 
			cellWidth		= (bottomWidth - marginRowLeft*2) / numOfCols;
			
			for (j = 0; j < numOfCols; ++j) {
				newCellRects[i][j].origin.x = marginRowLeft + cellWidth*j + leftMargin;
				newCellRects[i][j].origin.y = floorHeight + bottomMargin;
				newCellRects[i][j].size.width = newCellRects[i][j].size.height = (ceilingHeight - floorHeight);
			}
			
			floorWidth = ceilingWidth;
			ceilingWidth *= rowRatio;
			floorHeight = ceilingHeight;
			ceilingHeight = heightForWidth(ceilingWidth, bottomWidth, rateOfSlope);
		}
		
		retVal = YES;
	}
	else
		retVal = NO;
	
	return retVal;	
}

- (NSRect)rectForCell:(AKCellIndex)cellIndex {
	if (cellIndex >= AKDSQCellsCount)
		[[NSException exceptionWithName:NSInvalidArgumentException
								 reason:[NSString stringWithFormat:@"rectForCell: cellIndex:%d out of bound (%d)", cellIndex, AKDSQCellsCount]
							   userInfo:nil] raise];

	unsigned col = cellIndex % 9;
	unsigned row = cellIndex / 7;

	return cellRects[row][col];
}

@end

/** @} */
